home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 317 / asmsrc / symbols.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-20  |  8.9 KB  |  316 lines

  1. /* symbols.c -symbol table- */
  2.  
  3. /* Copyright (C) 1987 Free Software Foundation, Inc.
  4.  
  5. This file is part of Gas, the GNU Assembler.
  6.  
  7. The GNU assembler is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Assembler General
  12. Public License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. the GNU Assembler, but only under the conditions described in the
  16. GNU Assembler General Public License.  A copy of this license is
  17. supposed to have been given to you along with the GNU Assembler
  18. so you can know your rights and responsibilities.  It should be
  19. in a file named COPYING.  Among other things, the copyright
  20. notice and this notice must be preserved on all copies.  */
  21.  
  22.  
  23. #include "as.h"
  24. #include "hash.h"
  25. #include "obstack.h"        /* For "symbols.h" */
  26. #include "struc-symbol.h"
  27. #include "symbols.h"
  28. #include "frags.h"
  29.  
  30. static
  31. struct hash_control *
  32. sy_hash;            /* symbol-name => struct symbol pointer */
  33.  
  34.                 /* Below are commented in "symbols.h". */
  35. unsigned int local_bss_counter;
  36. symbolS * symbol_rootP;
  37. symbolS * symbol_lastP;
  38. symbolS    abs_symbol;
  39. struct obstack    notes;
  40.  
  41.  
  42.  
  43. symbolS * symbol_find();    /* Keep C compiler happy. */
  44.  
  45. /*
  46.  * Un*x idea of local labels. They are made by "n:" where n
  47.  * is any decimal digit. Refer to them with
  48.  *  "nb" for previous (backward) n:
  49.  *  or "nf" for next (forward) n:.
  50.  *
  51.  * Like Un*x AS, we have one set of local label counters for entire assembly,
  52.  * not one set per (sub)segment like in most assemblers. This implies that
  53.  * one can refer to a label in another segment, and indeed some crufty
  54.  * compilers have done just that.
  55.  *
  56.  * I document the symbol names here to save duplicating words elsewhere.
  57.  * The mth occurence of label n: is turned into the symbol "Ln^Am" where
  58.  * n is a digit and m is a decimal number. "L" makes it a label discarded
  59.  * unless debugging and "^A"('\1') ensures no ordinary symbol SHOULD get the
  60.  * same name as a local label symbol. The first "4:" is "L4^A1" - the m
  61.  * numbers begin at 1.
  62.  */
  63.  
  64. typedef short unsigned int
  65. local_label_countT;
  66.  
  67. static local_label_countT
  68. local_label_counter[10];
  69.  
  70. static                /* Returned to caller, then copied. */
  71.   char symbol_name_build[12];    /* used for created names ("4f") */
  72.  
  73. void
  74. symbol_begin()
  75. {
  76.   symbol_lastP = NULL;
  77.   symbol_rootP = NULL;        /* In case we have 0 symbols (!!) */
  78.   sy_hash = hash_new();
  79.   bzero ((char *)(& abs_symbol), sizeof(abs_symbol));
  80.   abs_symbol . sy_type = N_ABS;    /* Can't initialise a union. Sigh. */
  81.   bzero ((char *)(local_label_counter), sizeof(local_label_counter) );
  82.   local_bss_counter = 0;
  83. }
  84.  
  85. /*
  86.  *            local_label_name()
  87.  *
  88.  * Caller must copy returned name: we re-use the area for the next name.
  89.  */
  90.  
  91. char *                /* Return local label name. */
  92. local_label_name(n, augend)
  93.      register int n;    /* we just saw "n:", "nf" or "nb" : n a digit */
  94.      register int augend; /* 0 for nb, 1 for n:, nf */
  95. {
  96.   register char *    p;
  97.   register char *    q;
  98.   char symbol_name_temporary[10]; /* build up a number, BACKWARDS */
  99.  
  100.   know( n >= 0 );
  101.   know( augend == 0 || augend == 1 );
  102.   p = symbol_name_build;
  103.   * p ++ = 'L';
  104.   * p ++ = n + '0';        /* Make into ASCII */
  105.   * p ++ = 1;            /* ^A */
  106.   n = local_label_counter [ n ] + augend;
  107.                 /* version number of this local label */
  108.   /*
  109.    * Next code just does sprintf( {}, "%d", n);
  110.    * It is more elegant to do the next part recursively, but a procedure
  111.    * call for each digit emitted is considered too costly.
  112.    */
  113.   q = symbol_name_temporary;
  114.   for (*q++=0; n; q++)        /* emits NOTHING if n starts as 0 */
  115.     {
  116.       know(n>0);        /* We expect n > 0 always */
  117.       *q = n % 10 + '0';
  118.       n /= 10;
  119.     }
  120.   while ( * p ++ = * -- q )
  121.     {
  122.     }
  123.   /* The label, as a '\0' ended string, starts at symbol_name_build. */
  124.   return (symbol_name_build);
  125. }
  126.  
  127.  
  128. void
  129. local_colon (n)
  130.      int        n;    /* just saw "n:" */
  131. {
  132.   local_label_counter [n] ++;
  133.   colon (local_label_name (n, 0));
  134. }
  135.  
  136. /*
  137.  *            symbol_new()
  138.  *
  139.  * Return a pointer to a new symbol.
  140.  * Die if we can't make a new symbol.
  141.  * Fill in the symbol's values.
  142.  * Add symbol to end of symbol chain.
  143.  *
  144.  *
  145.  * Please always call this to create a new symbol.
  146.  *
  147.  * Changes since 1985: Symbol names may not contain '\0'. Sigh.
  148.  */
  149.  
  150. symbolS *
  151. symbol_new (name, type, other, desc, value, frag)
  152.      char *        name;    /* We copy this: OK to alter your copy. */
  153.      unsigned char    type;    /* As in <a.out.h>. */
  154.      char        other;    /* As in <a.out.h>. */
  155.      short int        desc;    /* As in <a.out.h>. */
  156.      valueT        value;    /* As in <a.out.h>, often an address. */
  157.                 /* Often used as offset from frag address. */
  158.      struct frag *    frag;    /* For sy_frag. */
  159. {
  160.   register symbolS *        symbolP;
  161.   register char *        preserved_copy_of_name;
  162.   register unsigned int        name_length;
  163.            char *        p;
  164.  
  165.   name_length = strlen(name) + 1;
  166.   obstack_grow(¬es,name,name_length);
  167.   p=obstack_finish(¬es);
  168.   /* obstack_1done( ¬es, name, name_length, &p ); */
  169.   preserved_copy_of_name = p;
  170.   p=obstack_alloc(¬es,sizeof(struct symbol));
  171.   /* obstack_1blank( ¬es, sizeof(struct symbol), &p ); */
  172.   symbolP            = (symbolS *) p;
  173.   symbolP -> sy_name        = preserved_copy_of_name;
  174.   symbolP -> sy_type        = type;
  175.   symbolP -> sy_other        = other;
  176.   symbolP -> sy_desc        = desc;
  177.   symbolP -> sy_value        = value;
  178.   symbolP -> sy_frag        = frag;
  179.   symbolP -> sy_next        = NULL;    /* End of chain. */
  180.   symbolP -> sy_forward        = NULL; /* JF */
  181. #ifdef SUSPECT
  182.   symbolP -> sy_name_offset    = ~ 0; /* Impossible offset catches errors. */
  183.   symbolP -> sy_number        = ~ 0; /* Ditto. */
  184. #endif
  185.   /*
  186.    * Link to end of symbol chain.
  187.    */
  188.   if (symbol_lastP)
  189.     {
  190.       symbol_lastP -> sy_next = symbolP;
  191.     }
  192.   else
  193.     {
  194.       symbol_rootP = symbolP;
  195.     }
  196.   symbol_lastP = symbolP;
  197.  
  198.   return (symbolP);
  199. }
  200.  
  201. /*
  202.  *            colon()
  203.  *
  204.  * We have just seen "<name>:".
  205.  * Creates a struct symbol unless it already exists.
  206.  *
  207.  * Gripes if we are redefining a symbol incompatibly (and ignores it).
  208.  *
  209.  */
  210. void
  211. colon (sym_name)        /* just seen "x:" - rattle symbols & frags */
  212.      register char *  sym_name; /* symbol name, as a cannonical string */
  213.                 /* We copy this string: OK to alter later. */
  214. {
  215.   register struct symbol * symbolP; /* symbol we are working with */
  216.  
  217.   if (symbolP = symbol_table_lookup( sym_name ))
  218.     {
  219.       if ((symbolP -> sy_type & N_TYPE) == N_UNDF)
  220.     {
  221.       if(   symbolP -> sy_other == 0
  222.          && symbolP -> sy_desc  == 0
  223.          && symbolP -> sy_value == 0)
  224.         {
  225.           symbolP -> sy_frag  = frag_now;
  226.           symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal;
  227.           know( N_UNDF == 0 );
  228.           symbolP -> sy_type |= seg_N_TYPE [(int) now_seg]; /* keep N_EXT bit */
  229.         }
  230.       else
  231.         {
  232.           as_warn( "Symbol \"%s\" is already %s/%d.%d.%d.",
  233.               sym_name,
  234.               seg_name [(int) N_TYPE_seg [symbolP -> sy_type & N_TYPE]],
  235.               symbolP -> sy_other, symbolP -> sy_desc,
  236.               symbolP -> sy_value);
  237.         }
  238.     }
  239.       else
  240.     {
  241. /* is 2 pass really needed. we can always have a special flavour of relax()
  242. that understands to convert (undf-undf+n) into whatever... */
  243.       lose();
  244.     }
  245.     }
  246.   else
  247.     {
  248.       symbolP = symbol_new (sym_name, (unsigned char)(seg_N_TYPE [(int) now_seg]), 0, 0,
  249.                 (valueT)(obstack_next_free(& frags) - frag_now -> fr_literal), frag_now);
  250.       symbol_table_insert (symbolP);
  251.     }
  252. }
  253.  
  254.  
  255. /*
  256.  *            symbol_table_insert()
  257.  *
  258.  * Die if we can't insert the symbol.
  259.  *
  260.  */
  261.  
  262. void
  263. symbol_table_insert (symbolP)
  264.      struct symbol *    symbolP;
  265. {
  266.   register char *    error_string;
  267.  
  268.   know( symbolP );
  269.   know( symbolP -> sy_name );
  270.   if ( * (error_string = hash_jam (sy_hash, symbolP -> sy_name, (char *)symbolP)))
  271.     {
  272.       as_fatal( "Inserting \"%s\" into symbol table failed: %s",
  273.           symbolP -> sy_name, error_string);
  274.     }
  275. }
  276.  
  277. /*
  278.  *            symbol_find_or_make()
  279.  *
  280.  * If a symbol name does not exist, create it as undefined, and insert
  281.  * it into the symbol table. Return a pointer to it.
  282.  */
  283. symbolS *
  284. symbol_find_or_make (name)
  285.      char *    name;
  286. {
  287.   register symbolS *    symbolP;
  288.  
  289.   symbolP = symbol_table_lookup (name);
  290.   if (symbolP == NULL)
  291.     {
  292.       symbolP = symbol_new (name, N_UNDF, 0, 0, 0, & zero_address_frag);
  293.       symbol_table_insert (symbolP);
  294.     }
  295.   return (symbolP);
  296. }
  297.  
  298. /*
  299.  *            symbol_find()
  300.  * 
  301.  * Implement symbol table lookup.
  302.  * In:    A symbol's name as a string: '\0' can't be part of a symbol name.
  303.  * Out:    NULL if the name was not in the symbol table, else the address
  304.  *    of a struct symbol associated with that name.
  305.  */
  306.  
  307. symbolS *
  308. symbol_find (name)
  309.      char *    name;
  310. {
  311.   return ( (symbolS *) hash_find( sy_hash, name ));
  312. }
  313.  
  314.  
  315. /* end: symbols.c */
  316.